{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ciphertext"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ciphertext = [\n",
    "    b'm\\x99QH\\xfc\\x99\\xcel\\xfc>\\x11\\xf81\\xda:\\x15\"6\\xd3b\\x07\\x7f\\xed\\x87\\xd5\\xd4\\xf0\\xbb',\n",
    "    b'x\\x96^\\r\\xb5\\x83\\x86u\\xeel\\x0e\\xf8,\\xce:\\x06 6\\xd0b\\nx\\xfd\\x87\\xd9\\xc9\\xe8',\n",
    "    b'm\\x90O^\\xfc\\x80\\xd3f\\xe7>\\x16\\xf46\\x89w\\x05r8\\xcb-\\x04',\n",
    "    b'`\\x97O\\r\\xbd\\x9f\\xc3%\\xe1q\\x0e\\xb15\\xdbu\\x0e5y\\xca*\\x1c7\\xec\\xc2\\xd2\\xcb',\n",
    "    b\"m\\x90[Y\\xfc\\x80\\xdf%\\xeb\\x7f\\x03\\xe2b\\xc1{\\x167y\\xdf'\\x16y\\xa8\\xc6\\x97\\xc2\\xed\\xa9p(\",\n",
    "    b'`\\x9dN\\r\\xb5\\x8b\\x86m\\xe0n\\x1f\\xb1*\\xc8i@45\\xd25\\x1d7\\xe9\\xd0\\xd6\\xdf',\n",
    "    b'p\\x96\\x1aL\\xfc\\x83\\xcfb\\xe7jZ\\xfe0\\x89s\\x0er8\\x9d&\\x12n',\n",
    "    b'p\\x96\\x1aL\\xfc\\x9b\\xcfv\\xe6q\\x14\\xb1-\\xdb:\\t<y\\xd3-\\x1dr',\n",
    "    b'p\\x8b\\x1aD\\xa8\\xcd\\xd2m\\xeal\\x1f\\xf7-\\xdb\\x7f@&1\\xd8b\\x1fr\\xfb\\xd4\\x97\\xc1\\xf0\\xa2t',\n",
    "    b'x\\x94V\\r\\xa8\\x85\\xc7q\\xafi\\x1f\\xb11\\xcc\\x7f@=+\\x9d1\\x16r\\xe5',\n",
    "    b'p\\x8b\\x1aO\\xa9\\x99\\x86d\\xafz\\x08\\xf4#\\xc4:\\x17;-\\xd5+\\x1d7\\xe9\\x87\\xd3\\xd4\\xfa\\xad|',\n",
    "    b'p\\xd8IY\\xbd\\x83\\xc2%\\xees\\x13\\xf5b\\xddr\\x05r+\\xd2#\\x01',\n",
    "    b'v\\x9e\\x1aL\\xfc\\x9e\\xd3w\\xe9>\\x0e\\xfe0\\xc4\\x7f\\x0e&<\\xd9b\\x00\\x7f\\xe7\\xd5\\xd2',\n",
    "    b'x\\x96^\\r\\x95\\xcd\\xcej\\xe3zZ\\xe6+\\xddr\\t<y\\xd0;S\\x7f\\xe9\\xc9\\xd3',\n",
    "    b\"~\\x8a[D\\xb2\\x9e\\x86j\\xe9>\\x0e\\xf9'\\x89}\\x0f>=\\xd8,Sd\\xe9\\xc9\\xd3\",\n",
    "    b'q\\x97M\\r\\xba\\x88\\xd1%\\xf6{\\x0e\\xb1*\\xc6m@&1\\xd8;St\\xfa\\xc2\\xd2\\xd6',\n",
    "    b'm\\x90HB\\xa9\\x8a\\xce%\\xe2gZ\\xf7+\\xc7}\\x05 *\\x9d6\\x1c7\\xfc\\xcf\\xd2\\x86\\xfb\\xa9t5',\n",
    "    b'n\\x90SA\\xb9\\xcd\\xcf%\\xf8{\\x1f\\xe1b\\xder\\t><\\x9d\\x0bS`\\xed\\xc2\\xc7',\n",
    "    b'9\\xd8_I\\xbb\\x8c\\xd4%\\xeer\\x16\\xf0,\\x89j\\x0f7y\\x9dbS7\\xa8\\x87\\x97\\x86\\xbf',\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from string import ascii_lowercase\n",
    "\n",
    "# set of allowed characters\n",
    "letters = set(ascii_lowercase + ' ')\n",
    "\n",
    "# reconstructed messages\n",
    "plaintext = [''] * len(ciphertext)\n",
    "\n",
    "# take all the codes at the same position\n",
    "for messages in zip(*ciphertext):\n",
    "    keys = set()\n",
    "    \n",
    "    # find viable keys\n",
    "    for key in range(256):\n",
    "        for m in messages:\n",
    "            if chr(m ^ key) not in letters:\n",
    "                break\n",
    "        else:\n",
    "            keys.add(key)\n",
    "\n",
    "    key = keys.pop() if len(keys) == 1 else None\n",
    "\n",
    "    # reconstruct plaintext\n",
    "    for i, m in enumerate(messages):\n",
    "        if key is not None:\n",
    "            plaintext[i] += chr(m ^ key)\n",
    "        else:\n",
    "            plaintext[i] += '?'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['take?this kiss upon?t',\n",
       " 'and ?n parting from?y',\n",
       " 'thus?much let me av?w',\n",
       " 'you ?re not wrong w?o',\n",
       " 'that?my days have b?e',\n",
       " 'yet ?f hope has flo?n',\n",
       " 'in a?night or in a ?a',\n",
       " 'in a?vision or in n?n',\n",
       " 'is i? therefore the?l',\n",
       " 'all ?hat we see or ?e',\n",
       " 'is b?t a dream with?n',\n",
       " 'i st?nd amid the ro?r',\n",
       " 'of a?surf tormented?s',\n",
       " 'and ? hold within m? ',\n",
       " 'grai?s of the golde? ',\n",
       " 'how ?ew yet how the? ',\n",
       " 'thro?gh my fingers ?o',\n",
       " 'whil? i weep while ? ',\n",
       " '  ed?ar allan poe  ? ']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plaintext"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
